
/**
 * 插件名:自定义OP权限管理 v 0.0.3
 * 作者:Yoyo
 * QQ号:1294858802
 * 介绍:指对OP玩家权限进行限制
 * (咦咦咦 学习LXL开发的第三天 然后写了大半天才撸出来这个插件的:::有BUG请向我反馈)
 * !!!!!!!转载修改!!!!!!(请保留出处,和作者名谢谢)
 * 控制台:
 * 添加一个op权限插件管理员   opmanage add <玩家名> 
 * 移除一个op权限插件管理员 opmanage remove <玩家名>
 * 
 * 游戏内:
 * 打开op管理面板  /op管理
 * 
 *日期:2021/9/7
 */
//用啥数据库 OP能有几个??

//配置文件
//初始化配置信息
var configInt = '{"superOp":[],"blacklist":[],"public":["tp","say","time","weather","me","msg"],"op":{},"cmdblock":{}}';
//加载配置文件
const CONFIG = data.openConfig(".\\plugins\\Yoyo\\OpManage\\config.json","json",configInt);
lxl.export(isOpManage,"isOpManage");

//监听事件
mc.listen("onPlayerCmd",PlayerCmd);//玩家使用命令
mc.listen("onCmdBlockExecute",CmdBlockExecute);//命令方块
mc.listen("onNpcCmd",NpcCmd);//npc触发命令
mc.listen("onPlaceBlock",PlaceBlock);//放置方块
mc.listen("onDestroyBlock",DestroyBlock);// 玩家破坏方块完成
mc.listen("onJoin",Join);//玩家进入服务器(因为用到名称和Xuid,为了防止玩家改名,需要同步
mc.listen("onServerStarted",ServerStarted);


//注册命令
mc.regPlayerCmd("op管理","打开op管理面板",opManageFun,1);
mc.regPlayerCmd("opmanage","Open the OP management panel",opManageFun,1);//一个英文版的
mc.regConsoleCmd("opmanage add","添加一个op权限插件管理员 <玩家名>",opManageAdd);
mc.regConsoleCmd("opmanage remove","移除一个op权限插件管理员 <玩家名>",opManageRemove);

//监听方法
function PlayerCmd(player,cmd){//玩家使用命令
    if(!player.isOP()) return true;
    let isMOP = CONFIG.get("superOp");
    if(isMOP.indexOf(player.xuid) !== -1){
        //是插件管理不拦截
        return true;
    }
    if(!Yoyo.methods.isblacklist(cmd)){//黑名单
        player.tell("你无权使用该命令");
        return false;
    }
    if(!Yoyo.methods.isPublicBll(cmd) && !Yoyo.methods.isMyBll(player.xuid,cmd)){
        player.tell("你无权使用该命令");
        return false;
    }
    return true;
}

function CmdBlockExecute(cmd,pos){//命令方块
    let cmdBlockID = data.toMD5(`${pos.dimid}_${pos.x}_${pos.y}_${pos.z}`);
    let cmdblockS = CONFIG.get("cmdblock");
    let MyCmdBlockArr = cmdblockS[cmdBlockID];
    if(MyCmdBlockArr != null){
       //存在的命令方块
       let isMOP = CONFIG.get("superOp");
        if(isMOP.indexOf(MyCmdBlockArr) !== -1){
            //是插件管理不拦截
            return true;
        }
        if(!Yoyo.methods.isblacklist(cmd)){//黑名单
            return false;
        }
       if(!Yoyo.methods.isPublicBll(cmd) && !Yoyo.methods.isMyBll(MyCmdBlockArr,cmd)){
        return false;
        }else{
            return true;
        }
    }else{
        //没有记录的不管
    }
}

function PlaceBlock(player,block){//玩家放置方块
    if(block.type != "minecraft:command_block" && block.type != "minecraft:chain_command_block"&& block.type != "minecraft:repeating_command_block") return true;
    let isMOP = CONFIG.get("superOp");
    if(isMOP.indexOf(player.xuid) !== -1){
        //是插件管理不拦截
        return true;
    }
    let cmdBlockID = data.toMD5(`${block.pos.dimid}_${block.pos.x}_${block.pos.y}_${block.pos.z}`);
    let cmdblockS = CONFIG.get("cmdblock");
    let MyCmdBlockArr = cmdblockS[cmdBlockID];
    if(MyCmdBlockArr == null){
        cmdblockS[cmdBlockID] = player.xuid;
        CONFIG.set("cmdblock",cmdblockS);
        CONFIG.reload();
    }
    return true;
}

function DestroyBlock(player,block){// 玩家破坏方块完成
    if(block.type != "minecraft:command_block") return true;
    let cmdBlockID = data.toMD5(`${block.pos.dimid}_${block.pos.x}_${block.pos.y}_${block.pos.z}`);
    let cmdblockS = CONFIG.get("cmdblock");
    let MyCmdBlockArr = cmdblockS[cmdBlockID];
    if(MyCmdBlockArr != null){
        delete cmdblockS[cmdBlockID];
        CONFIG.set("cmdblock",cmdblockS);
        CONFIG.reload();
    }else{
        //没有记录的方块
    }
    return true;
}

function Join(player){//监听玩家进入服务器
    if(!player.isOP()) return true;
    let opConfig = CONFIG.get("op");
    let playerOp = opConfig[player.xuid];
    if(!playerOp) return true;
    if(playerOp.name == player.name) return true;
    playerOp.name = player.name;
    opConfig[player.xuid] = playerOp;
    CONFIG.set("op",opConfig);//更新玩家名
    CONFIG.reload();
}


function NpcCmd(npc,pl){//npc触发命令
}

function opManageFun(player,args){//打开UI界面
    let isMOP = CONFIG.get("superOp");
    if(isMOP.indexOf(player.xuid) === -1){
        player.tell("你没有权限执行该指令,请用控制台添加管理员");
        return false;
    }
    Yoyo.data.last = '';
    Yoyo.data.news = '';
    Yoyo.methods.utwHome(player);//主页
   //
}

function opManageAdd(args){//添加一个插件管理员
    let isMOP = CONFIG.get("superOp");
    let plXuid = data.name2xuid(args[0]);
    if(isMOP.indexOf(plXuid) === -1){
        
        if(!plXuid){
            colorLog("red","[op权限]"+args[0]+" 不存在本服务器内,这是一个找不到的玩家");
            return;
        }
        colorLog("green","[op权限]"+args[0]+" 添加为新OP权限插件管理员");
        isMOP.push(plXuid);
        CONFIG.set("superOp",isMOP);
        CONFIG.reload();
    }else{
        colorLog("red","[op权限]"+args[0]+" 已经是OP权限插件管理员了,请不要重复添加!");
    }
}

function opManageRemove(args){//移除一个插件管理员
    let isMOP = CONFIG.get("superOp");
    let plXuid = data.name2xuid(args[0]);
    if(isMOP.indexOf(plXuid) === -1){
        colorLog("red","[op权限]"+args[0]+"不是OP权限插件管理员,无法移除!我表示找不到");
    }else{
        isMOP.splice(isMOP.indexOf(plXuid),1);
        colorLog("yellow","[op权限]"+args[0]+" 已移除OP权限插件管理员,他已经没有权限了!");
        CONFIG.set("superOp",isMOP);
        CONFIG.reload();
    }
}

//方法
const Yoyo = {
    data:{
        last:'',
        news:'',
        PlXuid:''
    },
    methods:{
        //其它方法
        isPublicBll(cmd){//公共指令库检测
            let state = false;
            let publicCmd = CONFIG.get("public");
            for(key in publicCmd){
                var se =new RegExp(`^${publicCmd[key]}.*`);
                if(se.test(cmd)){
                    state = true;
                }
            }
            return state;
        },
        isMyBll(xuid,cmd){//自己指令库检测
            let state = false;
            let OpCmd = CONFIG.get("op");
            let Myplayer = OpCmd[xuid];
            if(Myplayer == null){
                OpCmd[xuid] = {"name":data.xuid2name(xuid),"cmd":[]};
                CONFIG.set("op",OpCmd);
                CONFIG.reload();
                return false;
            }
           let MyCmdArr =  Myplayer.cmd;
            for(key in MyCmdArr){
                var se =new RegExp(`^${MyCmdArr[key]}.*`);
                if(se.test(cmd)){
                    state = true;
                }
            }
            return state;
        },
        isblacklist(cmd){
            let isblack = true;
            let blacklist = CONFIG.get("blacklist");
            if(blacklist == null){
                blacklist = [];
            }
            for(blacKEY in blacklist){
                var se =new RegExp(`${blacklist[blacKEY]}`);
                if(se.test(cmd)){
                    isblack = false;
                    break;
                }
            }
            return isblack;
        },
        utwHome(player){//主菜单
            Yoyo.data.news = 'utwHome';//更新当前页面
            let utw = mc.newCustomForm();
            utw.setTitle("OP权限管理");
            utw.addLabel("欢迎使用Yoyo版,OP权限管理插件!\n遇到问题加QQ群:363457102\n下拉菜单最后的,重载配置,是你手动修改插件配置文件后,需要执行一遍才能导入生效!(手动改配置,请确定Json格式正确,不推荐手动修改),该插件不仅限制玩家输入命令,连指定玩家放置的命令方块也会记录!同样遵循规则!(不要以为是命令方块失效了哦...咦咦咦!)");
            utw.addDropdown("操作类型",["添加公共命令库","删除公共命令库","操作其它OP私有命令库","添加OP新记录","添加全局命令黑名单","删除全局命令黑名单","重载配置","清空OP权限管理"]);
            player.sendForm(utw,(player,data)=>{
                if(!data) return;
                switch(data[1]){
                    case 0:
                        //添加公共命令库
                        Yoyo.methods.utwPublicAdd(player,"utwHome");
                        break;
                    case 1:
                        //删除公共命令库
                        Yoyo.methods.utwPublicDel(player,"utwHome");
                        break;
                    case 2:
                        //操作其它OP私有命令库
                        Yoyo.methods.utwPlayerSelect(player,"utwHome");
                        break;
                    case 3:
                        //添加OP新记录
                        Yoyo.methods.utwAddOpPlayer(player,"utwHome");
                        break;
                    case 4:
                        //添加全局命令黑名单
                        Yoyo.methods.utwblacklistAdd(player,"utwHome");
                        break;
                    case 5:
                        //删除全局命令黑名单
                        Yoyo.methods.utwblacklistDel(player,"utwHome");
                        break;
                    case 6:
                        //重载配置
                        CONFIG.reload();
                        Yoyo.methods.utwend(player,"§2配置重载成功","utwHome");
                        break;
                    case 7:
                        //清空OP权限管理
                        let isMOP = CONFIG.get("superOp");
                        isMOP=[];
                        CONFIG.set("superOp",isMOP);
                        CONFIG.reload();
                        player.tell("§2清空成功,你已经没有权限进行操作了");
                        break;
                }
                
            });
        },
        utwPublicAdd(player,last){//添加公共命令库
            Yoyo.data.news = 'utwPublicAdd';//更新当前页面
            Yoyo.data.last = last;//上个界面
            let utw = mc.newCustomForm();
            utw.setTitle("添加公共命令库");
            utw.addLabel("重复的会添加失败的,分支命令会覆盖主命令\n比如:\n已添加 give \n如果再添加 give @s \n那么该分支会覆盖前面的主命令!");
            utw.addInput("命令不加/ :","请输入需要添加的命令");
            player.sendForm(utw,(player,data)=>{
                if(!data) return;
                let DelCmd = '';
                if(data[1] == ""){
                    Yoyo.methods.utwend(player,"§4你未输入内容,添加失败!","utwPublicAdd");
                    return;
                }
                if(!/^[^/].*/.test(data[1])){
                    Yoyo.methods.utwend(player,"§4指令不前面不需要添加/ 请重新输入","utwPublicAdd");
                    return;
                }
                let publicCmdArr = CONFIG.get("public");
                if(publicCmdArr.indexOf(data[1]) !== -1){
                    Yoyo.methods.utwend(player,"§4指令已存在请不要重复添加","utwPublicAdd");
                    return;
                }
                for(key in publicCmdArr){
                    var se =new RegExp(`^${publicCmdArr[key]}.*`);
                    if(se.test(data[1])){
                        DelCmd = publicCmdArr[key];
                        delete publicCmdArr[key];
                        
                    }
                }
                publicCmdArr.push(data[1]);
                CONFIG.set("public",publicCmdArr);
                CONFIG.reload();
                if(DelCmd!=''){
                    Yoyo.methods.utwend(player,"§2分支指令添加成功,并已替代它的主命令"+DelCmd,"utwPublicAdd");
                    return;
                }
                Yoyo.methods.utwend(player,"§2指令添加成功","utwPublicAdd");
                return;

            });
        },
        utwPublicDel(player,last){//删除公共命令库
            Yoyo.data.news = 'utwPublicDel';//更新当前页面
            Yoyo.data.last = last;//上个界面
            let publicCmd = CONFIG.get("public");
            let utw = mc.newCustomForm();
            utw.setTitle("删除公共命令库");
            utw.addDropdown("已有公共命令",publicCmd);
            utw.addSwitch("是否删除",true);
            player.sendForm(utw,(player,data)=>{
                if(!data) return;
                if(data[1] == 0){
                    Yoyo.methods.utwend(player,"§2[已取消删除]请选你要进行的操作","utwPublicDel");
                    return;
                }else{
                    publicCmd.splice(data[0],1);
                    CONFIG.set("public",publicCmd);
                    CONFIG.reload();
                    Yoyo.methods.utwend(player,"§2指令删除成功","utwPublicDel");
                    return;
                }
            });
        },
        utwPlayerSelect(player,last){//选择玩家
            Yoyo.data.news = 'utwPlayerSelect';//更新当前页面
            Yoyo.data.last = last;//上个界面
            let PlayerOp = CONFIG.get("op");
            let PlayerOpNameArr = [];
            for(playerXuid in PlayerOp){
                PlayerOpNameArr.push(PlayerOp[playerXuid].name);
            }
            let utw = mc.newCustomForm();
            utw.setTitle("选择进行管理的OP");
            utw.addLabel("这里的OP列表只显示,触发命令的OP用户!如果需要添加未记录的OP玩家请返回主菜单,在下拉菜单靠后选项!选择添加OP新记录");
            utw.addDropdown("已记录的OP",PlayerOpNameArr);
            utw.addSwitch("删除<->添加",true);
            player.sendForm(utw,(player,datas)=>{
                if(!datas) return;
                 Yoyo.data.PlXuid = data.name2xuid(PlayerOpNameArr[datas[1]]);
                if(datas[2] == 1){//添加
                    Yoyo.methods.utwPlayerAdd(player,"utwPlayerSelect");
                }else{//删除
                    Yoyo.methods.utwPlayerDel(player,"utwPlayerSelect");
                }
            });
        },
        utwPlayerAdd(player,last){//给其它OP添加命令库
            Yoyo.data.news = 'utwPlayerAdd';//更新当前页面
            Yoyo.data.last = last;//上个界面
            let xuid = Yoyo.data.PlXuid;
            let utw = mc.newCustomForm();
            utw.setTitle("添加OP私有命令库");
            utw.addLabel("重复的会添加失败的,分支命令会覆盖主命令\n比如:\n已添加 give \n如果再添加 give @s \n那么该分支会覆盖前面的主命令!");
            utw.addInput("命令不加/ :","请输入需要添加的命令");
            player.sendForm(utw,(player,data)=>{
                if(!data) return;
                let DelCmd = '';
                if(data[1] == ""){
                    Yoyo.methods.utwend(player,"§4你未输入内容,添加失败!","utwPlayerAdd");
                    return;
                }
                if(!/^[^/].*/.test(data[1])){
                    Yoyo.methods.utwend(player,"§4指令不前面不需要添加/ 请重新输入","utwPlayerAdd");
                    return;
                }
                let publicCmdArr = CONFIG.get("public");
                if(publicCmdArr.indexOf(data[1]) !== -1){
                    Yoyo.methods.utwend(player,"§4指令已存在公共库,私有无需添加","utwPlayerAdd");
                    return;
                }
                let OPCmdArr = CONFIG.get("op");
                let PLOPCmdArr = OPCmdArr[xuid].cmd;
                if(PLOPCmdArr.indexOf(data[1]) !== -1){
                    Yoyo.methods.utwend(player,"§4指令已存在请不要重复添加添加","utwPlayerAdd");
                    return;
                }
                for(key in PLOPCmdArr){
                    var se =new RegExp(`^${PLOPCmdArr[key]}.*`);
                    if(se.test(data[1])){
                        DelCmd = PLOPCmdArr[key];
                        delete PLOPCmdArr[key];
                        
                    }
                }
                PLOPCmdArr.push(data[1]);
                OPCmdArr[xuid].cmd = PLOPCmdArr;
                CONFIG.set("op",OPCmdArr);
                CONFIG.reload();
                if(DelCmd!=''){
                    Yoyo.methods.utwend(player,"§2分支指令添加成功,并已替代它的主命令"+DelCmd,"utwPlayerAdd");
                    return;
                }
                Yoyo.methods.utwend(player,"§2指令添加成功","utwPlayerAdd");
                return;
            });
        },
        utwPlayerDel(player,last){//给其它OP删除命令库
            Yoyo.data.news = 'utwPlayerDel';//更新当前页面
            Yoyo.data.last = last;//上个界面
            let xuid = Yoyo.data.PlXuid;
            let PlayerCmd = CONFIG.get("op");
            let OPPlayerCmd = PlayerCmd[xuid].cmd;
            let utw = mc.newCustomForm();
            utw.setTitle("删除OP私有命令库");
            utw.addDropdown("TA已有命令",OPPlayerCmd);
            utw.addSwitch("是否删除",true);
            player.sendForm(utw,(player,data)=>{
                if(!data) return;
                if(data[1] == 0){
                    Yoyo.methods.utwend(player,"§2[已取消删除]请选你要进行的操作","utwPlayerDel");
                    return;
                }else{
                    OPPlayerCmd.splice(data[0],1);
                    PlayerCmd[xuid].cmd = OPPlayerCmd;
                    CONFIG.set("op",PlayerCmd);
                    CONFIG.reload();
                    Yoyo.methods.utwend(player,"§2指令删除成功","utwPlayerDel");
                    return;
                }
            });
        },
        utwAddOpPlayer(player,last){//添加一个OP新记录
            Yoyo.data.news = 'utwAddOpPlayer';//更新当前页面
            Yoyo.data.last = last;//上个界面
            let utw = mc.newCustomForm();
            utw.setTitle("添加一个OP新记录");
            utw.addInput("存在服务器的玩家名:","请输入玩家名");
            player.sendForm(utw,(player,datas)=>{
                if(!datas) return;
                if(datas[0] == ""){
                    Yoyo.methods.utwend(player,"§4你未输入内容,添加失败!","utwAddOpPlayer");
                    return;
                }
                if(!/^[\w ]+/.test(datas[0])){
                    Yoyo.methods.utwend(player,"§4输入的字符不符合玩家名称规则,请重新输入","utwAddOpPlayer");
                    return;
                }
                let playerXuid = data.name2xuid(datas[0]);
                if(!playerXuid){
                    Yoyo.methods.utwend(player,"§4该玩家都没有进过本服务器添加个der!!","utwAddOpPlayer");
                    return;
                }
                let opPlayerList = CONFIG.get("op");
                if(opPlayerList[playerXuid] != null){
                    Yoyo.methods.utwend(player,"§4这个玩家已经存在OP记录列表了,请不要重复添加!","utwAddOpPlayer");
                    return;
                }
                opPlayerList[playerXuid] = {"name":playerXuid,"cmd":[]};
                CONFIG.set("op",opPlayerList);
                CONFIG.reload();
                Yoyo.methods.utwend(player,"§2成功添加新记录OP玩家!","utwAddOpPlayer");
                return;
                

            });
        },
        utwblacklistAdd(player,last){//命令黑名单添加
            Yoyo.data.news = 'utwblacklistAdd';//更新当前页面
            Yoyo.data.last = last;//上个界面
            let xuid = Yoyo.data.PlXuid;
            let utw = mc.newCustomForm();
            utw.setTitle("添加黑名单命令库");
            utw.addLabel("...说些什么好呢?\n用法如下:\n^give.*command_block_minecart.*\n这条指令是禁止give命令方块矿车\n这里如你所看我用了正则表达式!对的就是这样!");
            utw.addInput("命令不加/ :","请输入需要加入黑马单的命令匹配方式");
            player.sendForm(utw,(player,datas)=>{
                if(!datas) return;
                if(datas[1] == ""){
                    Yoyo.methods.utwend(player,"§4你未输入内容,添加失败!","utwblacklistAdd");
                    return;
                }
                if(!/^[^/].*/.test(datas[1])){
                    Yoyo.methods.utwend(player,"§4指令不前面不需要添加/ 请重新输入","utwblacklistAdd");
                    return;
                }
                let blacklist = CONFIG.get("blacklist");
                if(blacklist == null){
                    blacklist = ["^give.*command_block_minecart.*"];
                }
                if(blacklist.indexOf(datas[1]) !== -1){
                    Yoyo.methods.utwend(player,"§4指令已存在一样的","utwblacklistAdd");
                    return;
                }
                blacklist.push(datas[1]);
                CONFIG.set("blacklist",blacklist);
                CONFIG.reload();
                Yoyo.methods.utwend(player,"§2添加该命令进黑名单成功","utwblacklistAdd");
                return;
            });
        },
        utwblacklistDel(player,last){//命令黑名单删除
            Yoyo.data.news = 'utwblacklistDel';//更新当前页面
            Yoyo.data.last = last;//上个界面
            let blacklist = CONFIG.get("blacklist");
            let utw = mc.newCustomForm();
            utw.setTitle("删除黑名单命令库");
            utw.addDropdown("已有黑名单命令匹配方式",blacklist);
            utw.addSwitch("是否删除",true);
            player.sendForm(utw,(player,data)=>{
                if(!data) return;
                if(data[1] == 0){
                    Yoyo.methods.utwend(player,"§2[已取消删除]请选你要进行的操作","utwblacklistDel");
                    return;
                }else{
                    blacklist.splice(data[0],1);
                    CONFIG.set("blacklist",blacklist);
                    CONFIG.reload();
                    Yoyo.methods.utwend(player,"§2黑名单匹配指令删除成功","utwblacklistDel");
                    return;
                }
            });
        },
        utwend(player,txt,last){//询问界面
            Yoyo.data.news = 'utwend';//更新当前页面
            Yoyo.data.last = last;//上个界面
            let utw = mc.newSimpleForm();
            utw.setTitle("OP权限管理");
            utw.setContent(txt);//提示内容
            utw.addButton("返回继续");
            utw.addButton("返回菜单");
            utw.addButton("退出");
            player.sendForm(utw,(player,id)=>{
                if(id == 0){
                    Yoyo.methods[last](player,"utwHome");
                }else if(id == 1){
                    Yoyo.methods.utwHome(player);
                }else{//关闭弹窗
                    return;
                }
            });
        }

    }
};


function isOpManage() {
    return "yoyo";
}

function ServerStarted(){
    colorLog("green","[INFO] Yoyo版本OP管理插件加载完成!");
    colorLog("green","[INFO] Yoyo version OP management plug-in loaded!");
}
